﻿using VideoAnalysisWebApi.Models;
using VideoAnalysisWebApi.Services;

namespace VideoAnalysisWebApi.ServicesImpl
{
    public class VideoAnalysisConfigService : IVideoAnalysisConfigService
    {
        private readonly IStreamService _streamService;
        private readonly IAnalysisService _analysisService;

        private readonly object _lockObj = new object();

        private readonly List<VideoAnalysisViewModel> views = new List<VideoAnalysisViewModel>();

        public VideoAnalysisConfigService(
            IStreamService streamService,
            IAnalysisService analysisService)
        {
            _streamService = streamService;
            _analysisService = analysisService;
        }

        public IEnumerable<VideoAnalysisConfigModel> GetConfigs()
        {
            return new List<VideoAnalysisConfigModel>()
            {
                new VideoAnalysisConfigModel(){  Id=1,StreamId=1, AnalysisIds = new int[]{ 1,2,3} , Enabled=true },
                new VideoAnalysisConfigModel(){  Id=2,StreamId=2, AnalysisIds = new int[]{ 1,3} , Enabled=true},
                new VideoAnalysisConfigModel(){  Id=3,StreamId=3, AnalysisIds = new int[]{ 1,2} , Enabled=false}
            };
        }

        public void Flush()
        {
            var configs = GetConfigs();
            var streams = _streamService.GetStreams();
            var analysis = _analysisService.GetAnalysis();

            var results = new List<VideoAnalysisViewModel>();
            foreach (var config in configs)
            {
                var stream = streams.Where(x => x.Id == config.StreamId).First();
                var analysisItems = analysis.Where(x => config.AnalysisIds.Contains(x.Id)).ToList();
                foreach (var item in analysisItems)
                {
                    var result = new VideoAnalysisViewModel()
                    {
                        Name = $"{stream.Name}-{item.Name}",
                        ConfigId = config.Id,
                        StreamId = stream.Id,
                        StreamName = stream.Name,
                        StreamUrl = stream.Url,
                        AnalysisModelId = item.Id,
                        AnalysisModelName = item.Name,
                        AnalysisModelType = item.Type,
                        Status = config.Enabled ? VideoAnalysisStatus.Pending : VideoAnalysisStatus.UnEnabled,

                    };
                    AddViewItem(result);
                    results.Add(result);
                }
            }

            // 需要移除的
            var allViews = GetView();
            foreach (var viewItem in allViews)
            {
                var exists = results.Where(x => x.ConfigId == viewItem.ConfigId &&
                x.StreamId == viewItem.StreamId &&
                x.AnalysisModelId == viewItem.AnalysisModelId).Any();
                if (exists)
                {
                    continue;
                }

                // todo: 状态判断，是否需要停止分析服务
                RemoveViewItem(viewItem);
            }
        }

        public IEnumerable<VideoAnalysisViewModel> GetView()
        {
            lock (_lockObj)
            {
                return new List<VideoAnalysisViewModel>(views);
            }
        }

        public bool AddViewItem(VideoAnalysisViewModel viewItem)
        {
            if (viewItem == null)
            {
                throw new ArgumentNullException(nameof(viewItem));
            }

            lock (_lockObj)
            {
                var exists = views.Where(x => x.ConfigId == viewItem.ConfigId &&
                x.StreamId == viewItem.StreamId &&
                x.AnalysisModelId == viewItem.AnalysisModelId).Any();
                if (!exists)
                {
                    views.Add(viewItem);
                    return true;
                }
                return false;
            }
        }

        public bool RemoveViewItem(VideoAnalysisViewModel viewItem)
        {
            if (viewItem == null)
            {
                throw new ArgumentNullException(nameof(viewItem));
            }

            lock (_lockObj)
            {
                return views.Remove(viewItem);
            }
        }
    }
}
